package com.example.mz.dynamicdb.controller;

import com.example.mz.dynamicdb.bean.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.Random;

@RestController
public class ESController {

    @Autowired
    private RestHighLevelClient client;


    @GetMapping("createIndex")
    public String createIndex(){

        // 创建索引
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("user");
        CreateIndexResponse createIndexResponse = null;
        try {
            createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            return "1";
        }
        // 响应状态
        boolean acknowledged = createIndexResponse.isAcknowledged();
        System.out.println("创建索引状态 ：" + acknowledged);
        return "0";
    }

    @GetMapping("queryIndex")
    public String queryIndex(){

        // 查询索引
        GetIndexRequest getIndexRequest = new GetIndexRequest("user");
        GetIndexResponse getIndexResponse = null;
        try {
            getIndexResponse = client.indices().get(getIndexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 响应状态
        System.out.println("查询索引之Aliases ：" + getIndexResponse.getAliases());
        System.out.println("查询索引之Mappings ：" + getIndexResponse.getMappings().toString());
        System.out.println("查询索引之Settings ：" + getIndexResponse.getSettings());
        return "0";
    }

    @GetMapping("deleteIndex")
    public String deleteIndex(){

        // 删除索引
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("user");
        AcknowledgedResponse response = null;
        try {
            response = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 响应状态
        System.out.println("删除索引 ：" + response.isAcknowledged());
        return "0";
    }

    @GetMapping("addDocument")
    public String addDocument(){

        //新增文档，创建请求对象
        IndexRequest indexRequest = new IndexRequest();
        // 设置索引及唯一性标识
        indexRequest.index("user").id("01");
        //设置索引及唯一性标识
        User user = new User();
        user.setName("上海");
        user.setAge(22);
        user.setSex("男");

        // 向ES插入数据，必须将数据转换位JSON格式
        ObjectMapper mapper = new ObjectMapper();
        String userJson = null;
        try {
            userJson = mapper.writeValueAsString(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        indexRequest.source(userJson, XContentType.JSON);
        //发送请求，获取响应对象
        IndexResponse indexResponse = null;
        try {
            indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("新增文档的状态：" + indexResponse.getResult());
        return "0";
    }

    @GetMapping("batchDocument")
    public String batchDocument(){

        // 创建批量新增请求对象
        BulkRequest bulkRequest = new BulkRequest();
        for (int i = 1; i <= 10 * 10000 ; i++) {
            Random random = new Random();
            int age = random.nextInt(50);
            String sex = (age % 2 == 0 ? "男" : "女");
            bulkRequest.add(new IndexRequest().index("user").source(XContentType.JSON, "name", "name" + i, "age",age , "sex", sex));

        }

        BulkResponse bulkResponse = null;
        try {
            bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("批量插，Took: " + bulkResponse.getTook());
        System.out.println("批量插入，Items: " + bulkResponse.getItems());
        return "0";
    }

    @GetMapping("updateDocument")
    public String updateDocument(){

        // 修改文档
        UpdateRequest updateRequest = new UpdateRequest();
        //配置修改参数
        updateRequest.index("user").id("01");
        //设置请求体，对数据进行修改
        String name = "小白";
        updateRequest.doc(XContentType.JSON, "name", name);
        updateRequest.doc(XContentType.JSON, "sex", "女");
        //发送请求，获取响应对象
        UpdateResponse updateResponse = null;
        try {
            updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("index:" + updateResponse.getIndex());
        System.out.println("id:" + updateResponse.getId());
        System.out.println("result:" + updateResponse.getResult());
        return "0";
    }

    @GetMapping("queryDocument")
    public String queryDocument(){

        //创建请求对象
        GetRequest request = new GetRequest().index("user").id("01");
        //客户端发送请求，获取响应对象
        GetResponse response = null;
        try {
            response = client.get(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("index:" + response.getIndex());
        System.out.println("type:" + response.getType());
        System.out.println("id:" + response.getId());
        System.out.println("source:" + response.getSourceAsString());
        return "0";
    }


    @GetMapping("deleteDocument")
    public String deleteDocument(){

        // 创建ES客户端

        DeleteRequest request = new DeleteRequest();
        request.index("user").id("02");

        DeleteResponse response = null;
        try {
            response = client.delete(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(response.toString());
        return "0";
    }

    @GetMapping("batchDeleteDocument")
    public String batchDeleteDocument(){

        // 批量删除数据
        BulkRequest request = new BulkRequest();
        request.add(new DeleteRequest().index("user").id("02"));
        request.add(new DeleteRequest().index("user").id("03"));
        request.add(new DeleteRequest().index("user").id("04"));
        BulkResponse response = null;
        try {
            response = client.bulk(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(response.getTook());
        int status = response.status().getStatus();
        System.out.println(response.getItems());
        return "0";
    }

    @GetMapping("queryAllIndex")
    public String queryAllIndex(){

        // 创建搜索请求对象
        SearchRequest request = new SearchRequest();
        request.indices("user");
        // 构建查询的请求体
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
        request.source(searchSourceBuilder);
        // 查询匹配
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        SearchHits hits = response.getHits();

        System.out.println("耗时：" + response.getTook());
        System.out.println("命中条数：" + hits.getTotalHits());
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        return "0";
    }

    @GetMapping("queryByTerm")
    public String queryByTerm(){

        SearchRequest request = new SearchRequest();
        request.indices("user");

        request.source(new SearchSourceBuilder().query(QueryBuilders.termQuery("name", "小白")));
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        SearchHits hits = response.getHits();

        System.out.println("耗时：" + response.getTook());
        System.out.println("命中条数：" + hits.getTotalHits());

        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        return "0";
    }

    @GetMapping("queryByPage")
    public String queryByPage(){

        SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
        // (当前页码-1)*每页显示数据条数
        builder.from(0);
        builder.size(2);
        request.source(builder);
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        SearchHits hits = response.getHits();

        System.out.println("耗时：" + response.getTook());
        System.out.println("命中条数：" + hits.getTotalHits());

        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        return "0";
    }

    @GetMapping("queryBySort")
    public String queryBySort(){

        SearchRequest request = new SearchRequest();
        request.indices("user");
        SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
        // 排序
        builder.sort("age", SortOrder.DESC);
        request.source(builder);
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        SearchHits hits = response.getHits();

        System.out.println("耗时：" + response.getTook());
        System.out.println("命中条数：" + hits.getTotalHits());

        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        return "0";
    }

    @GetMapping("fieldFilter")
    public String fieldFilter(){

        SearchRequest request = new SearchRequest();
        request.indices("user");
        SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
        // 排除字段
        String[] excludes = {};
        // 包含字段
        String[] includes = {"name"};
        builder.fetchSource(includes, excludes);
        request.source(builder);
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        SearchHits hits = response.getHits();

        System.out.println("耗时：" + response.getTook());
        System.out.println("命中条数：" + hits.getTotalHits());

        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        return "0";
    }


    @GetMapping("queryByBool")
    public String queryByBool(){

        SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 必须包含
        boolQueryBuilder.must(QueryBuilders.matchQuery("name", "小白"));
        // 一定不含
        boolQueryBuilder.mustNot(QueryBuilders.matchQuery("sex", "男"));
        // 可能包含
        boolQueryBuilder.should(QueryBuilders.matchQuery("age", 20));
        boolQueryBuilder.should(QueryBuilders.matchQuery("age", 22));

        builder.query(boolQueryBuilder);

        request.source(builder);
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        SearchHits hits = response.getHits();

        System.out.println("耗时：" + response.getTook());
        System.out.println("命中条数：" + hits.getTotalHits());

        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        return "0";
    }

    @GetMapping("queryByRange")
    public String queryByRange(){

        SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder builder = new SearchSourceBuilder();
        RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("age");

        rangeQuery.gte(15);
        rangeQuery.lt(30);
        builder.query(rangeQuery);

        request.source(builder);
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        SearchHits hits = response.getHits();

        System.out.println("耗时：" + response.getTook());
        System.out.println("命中条数：" + hits.getTotalHits());

        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        return "0";
    }

    @GetMapping("queryByFuzz")
    public String queryByFuzz(){


        SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.fuzzyQuery("name", "白").fuzziness(Fuzziness.TWO));

        request.source(builder);
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        SearchHits hits = response.getHits();

        System.out.println("耗时：" + response.getTook());
        System.out.println("命中条数：" + hits.getTotalHits());

        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        return "0";
    }

    @GetMapping("queryHighLight")
    public String queryHighLight(){


        SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder builder = new SearchSourceBuilder();
        TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("name", "小白");
        // 构建高亮字段
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        // 前置标签
        highlightBuilder.preTags("<font color='red'>");
        // 后置标签
        highlightBuilder.postTags("</font>");
        // 高亮字段
        highlightBuilder.field("name");
        //设置高亮构建对象
        builder.highlighter(highlightBuilder);

        builder.query(termsQueryBuilder);
        request.source(builder);
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(response.toString());
        SearchHits hits = response.getHits();
        System.out.println("耗时：" + response.getTook());
        System.out.println("命中条数：" + hits.getTotalHits());

        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        return "0";
    }

    @GetMapping("queryByGather")
    public String queryByGather(){

        SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder builder = new SearchSourceBuilder();

        AggregationBuilder aggregationBuilder1 = AggregationBuilders.max("maxAge").field("age");
        builder.aggregation(aggregationBuilder1);

        AggregationBuilder aggregationBuilder2 = AggregationBuilders.avg("avgAge").field("age");
        builder.aggregation(aggregationBuilder2);

        request.source(builder);
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println(response);
        SearchHits hits = response.getHits();
        System.out.println("耗时：" + response.getTook());
        System.out.println("命中条数：" + hits.getTotalHits());

        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        return "0";
    }

    @GetMapping("queryByGroup")
    public String queryByGroup(){

        SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder builder = new SearchSourceBuilder();

        AggregationBuilder aggregationBuilder = AggregationBuilders.terms("ageGroup").field("age");
        builder.aggregation(aggregationBuilder);

        request.source(builder);
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        SearchHits hits = response.getHits();
        System.out.println("耗时：" + response.getTook());
        System.out.println("命中条数：" + hits.getTotalHits());

        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        return "0";
    }



}
